package cmd

import (
	"context"
	"os"
	"os/signal"
	"syscall"

	log "application/v3/pkg/logger"
	"github.com/spf13/cobra"
)

func run(_ *cobra.Command, _ []string) error {
	_, cancel := context.WithCancel(context.Background())
	defer cancel()

	runTasks()
	runListenSignal()

	return nil
}

func runListenSignal() {
	sigChan := make(chan os.Signal)
	exitChan := make(chan struct{})
	signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
	log.WithField("signal", <-sigChan).Info("signal received")
	go func() {
		log.Warning("stopping chirpstack-application-server")
		// todo: handle graceful shutdown?
		exitChan <- struct{}{}
	}()

	select {
	case <-exitChan:
	case s := <-sigChan:
		log.WithField("signal", s).Info("signal received, stopping immediately")
	}
}

func runTasks() {
	tasks := []func() error{
		setLogLevel,
		setSyslog,
		setGRPCResolver,
		printStartMessage,
		setupStorage,
		setupNetworkServer,
		migrateGatewayStats,
		migrateToClusterKeys,
		setupIntegration,
		setupCodec,
		handleDataDownPayloads,
		startGatewayPing,
		setupAPI,
	}

	for _, task := range tasks {
		if err := task(); err != nil {
			log.Fatal(err)
		}
	}
}
